home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Everything For A Hacker
/
19990506-[HACK].iso
/
HEXEDIT
/
CROSSASM
/
CUG292WK.ARJ
/
PCDSK3
/
AST09.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-01-22
|
51KB
|
1,724 lines
.title assist09 - mc6809 monitor
.module assist09
.radix d
;* Modification date: November 23, 1988
;********************************************************
;* miscelaneous equates
;********************************************************
dftchp = 0 ; default character pad count
dftnlp = 0 ; default new line pad count
prompt = '> ; prompt character
numbkp = 8 ; number of breakpoints
eot = 0x04 ; end of transmission
bell = 0x07 ; bell character
lf = 0x0a ; line feed
cr = 0x0d ; carriage return
can = 0x18 ; cancel (ctl-x)
.page
.sbttl SWI Functions
;********************************************************
;* assist09 monitor swi functions
;*
;* the following equates define functions provided
;* by the assist09 monitor via the swi instruction.
;********************************************************
inchnp = 0 ; input char in a reg - no parity
outch = 1 ; output char from a reg
pdata1 = 2 ; output string
pdata = 3 ; output cr/lf then string
out2hs = 4 ; output two hex and space
out4hs = 5 ; output four hex and space
pcrlf = 6 ; output cr/lf
space = 7 ; output a space
monitr = 8 ; enter assist09 monitor
vctrsw = 9 ; vector examine/switch
brkpt = 10 ; user program breakpoint
pause = 11 ; task pause function
numfun = 11 ; number of available functions
;* sub-codes for accessing the vector table.
;* they are equivalent to offsets in the table.
;* relative positioning must be maintained.
.avtbl = 0 ; address of vector table
.cmdl1 = 2 ; first command list
.rsvd = 4 ; reserved hardware vector
.swi3 = 6 ; swi3 routine
.swi2 = 8 ; swi2 routine
.firq = 10 ; firq routine
.irq = 12 ; irq routine
.swi = 14 ; swi routine
.nmi = 16 ; nmi routine
.reset = 18 ; reset routine
.cion = 20 ; console on
.cidta = 22 ; console input data
.cioff = 24 ; console input off
.coon = 26 ; console output on
.codta = 28 ; console output data
.cooff = 30 ; console output off
.hsdta = 32 ; high speed printdata
.bson = 34 ; punch/load on
.bsdta = 36 ; punch/load data
.bsoff = 38 ; punch/load off
.pause = 40 ; task pause routine
.expan = 42 ; expression analyzer
.cmdl2 = 44 ; second command list
.pad = 46 ; character pad and new line pad
.echo = 48 ; echo/load and null bkpt flag
numvtr = 48/2+1 ; number of vectors
hivtr = 48 ; highest vector offset
.page
.sbttl Work Area
;********************************************************
;* work area
;*
;* The direct page register during most routine
;* operations will point to this work area. the Stack
;* initially starts under the reserved work areas as
;* defined herein.
;********************************************************
.area WORKPG (ABS,OVR)
.setdp 0
workpg: ; beginning of work aera
.blkb 0d256-(endpg-astack) ; stack space
astack: ; top of assist09 stack
tstack: .blkb 0d21 ; temporary stack hold
delim: .blkb 1 ; expression delimiter/work byte
misflg: .blkb 1 ; load cmd/thru breakpoint flag
swicnt: .blkb 1 ; trace "swi" nest level count
pcnter: .blkb 2 ; last program counter
pstack: .blkb 2 ; command recovery stack
rstack: .blkb 2 ; reset stack pointer
anumber:.blkb 2 ; binary build area
basepg: .blkb 1 ; base page value
addr: .blkb 2 ; address pointer value
window: .blkb 2 ; window
bkptop: .blkb 0x10 ; breakpoint opcode table
bkptbl: .blkb 0x10 ; breakpoint table
vectab: .blkb 0x32 ; vector table
bkptct: .blkb 1 ; breakpoint count
swibfl: .blkb 1 ; bypass swi as breakpoint flag
pauser: .blkb 4 ; pause routine
endpg:
.page
.sbttl Assist09 Code
.area ASSIST09 (ABS,OVR)
;********************************************************
;* bldvtr - build assist09 vector table
;*
;* hardware reset calls this subroutine to build the
;* assist09 vector table.
;*
;* input: s->valid stack ram
;* output: u->vector table address
;* dpr->assist09 work area page
;* the vector table and defaults are initialized
;*
;* all registers volatile
;********************************************************
bldvtr: leax vectab,pcr ; address vector table
tfr x,d ; obtain base page address
tfr a,dp ; setup dpr
sta *basepg ; store for quick reference
leau ,x ; return table to caller
stu ,x++ ; and init vector table address
ldb #numvtr-3 ; number relocatable vectors
pshs b ; store index on stack
leay initvt,pcr ; load from addr
1$: tfr y,d ; prepare address resolve
addd ,y++ ; to absolute address
std ,x++ ; into vector table
dec ,s ; count down
bne 1$ ; branch if more to insert
ldb #intve-intvs ; static value init length
2$: lda ,y+ ; load next byte
sta ,x+ ; store into position
decb ; count down
bne 2$ ; loop until done
puls pc,b ; return to initializer
;********************************************************
;* reset entry point
;*
;* hardware reset enters here if assist09 is enabled
;* to receive the mc6809 hardware vectors. we call
;* the bldvtr subroutine to initialize the vector
;* table, stack, and then fireup the monitor via swi
;* call.
;********************************************************
reset: leas astack,pcr ; setup initial stack
bsr bldvtr ; build vector table
1$: clra ; issue startup message
tfr a,dp ; default to page zero
swi ; perform monitor fireup
.byte monitr ; to enter command processing
bra 1$ ; reenter monitor if 'continue'
.page
.sbttl Vector Table
;********************************************************
;* initvt - initialize vector table
;*
;* this table is relocated to ram and represents the
;* initial state of the vector table. all addresses
;* are converted to absolute form. this table starts
;* with the second entry, ends with static constant
;* initialization data which carries beyond the table.
;********************************************************
initvt: .word cmdtb1-. ; default first command table
.word rsrvdr-. ; default undefined hardware vector
.word swi3r-. ; default swi3
.word swi2r-. ; default swi2
.word firqr-. ; default firq
.word irqr-. ; default irq routine
.word swir-. ; default swi routine
.word nmir-. ; default nmi routine
.word reset-. ; restart vector
.word cion-. ; default cion
.word cidta-. ; default cidta
.word cioff-. ; default cioff
.word coon-. ; default coon
.word codta-. ; default codta
.word cooff-. ; default cooff
.word hsdta-. ; default hsdta
.word bson-. ; default bson
.word bsdta-. ; default bsdta
.word bsoff-. ; default bsoff
.word cpause-. ; default pause routine
.word exp1-. ; default expression analyzer
.word cmdtb2-. ; default second command table
;* constants
;*
intvs: .byte dftchp,dftnlp ; default null padds
.word 0 ; default echo
.byte 0 ; initial breakpoint count
.byte 0 ; swi breakpoint level
rts ; default pause routine
intve = .
.page
.sbttl SWI Handler
;********************************************************
;* assist09 swi handler
;*
;* the swi handler provides all interfacing necessary
;* for a user program. a function byte is assumed to
;* follow the swi instruction. it is bound checked
;* and the proper routine is given control. this
;* invocation may also be a breakpoint interrupt.
;* if so, the breakpoint handler is entered.
;*
;* input: machine state defined for swi
;* output: varies according to function called. pc on
;*
;* callers stack incremented by one if valid call.
;* volatile registers: see functions called
;*
;* state: runs disabled unless function clears i flag.
;********************************************************
;* swi function vector table
swivtb: .word zinch-swivtb ; inchnp
.word zotch1-swivtb ; outch
.word zpdta1-swivtb ; pdata1
.word zpdata-swivtb ; pdata
.word zot2hs-swivtb ; out2hs
.word zot4hs-swivtb ; out4hs
.word zpcrlf-swivtb ; pcrlf
.word zspace-swivtb ; space
.word zmontr-swivtb ; monitr
.word zvswth-swivtb ; vctrsw
.word zbkpnt-swivtb ; breakpoint
.word zpause-swivtb ; task pause
swir: dec swicnt,pcr ; up "swi" level for trace
lbsr lddp ; setup page and verify stack
;* check for breakpoint trap
ldu 10,s ; load program counter
leau -1,u ; back to swi address
tst *swibfl ; this "swi" breakpoint ?
bne 2$ ; no - branch to let through
lbsr cbkldr ; obtain breakpoint pointers
negb ; obtain positive count
1$: decb ; count down
bmi 2$ ; branch when done
cmpu ,y++ ; ? was this a breakpoint
bne 1$ ; branch if not
stu 10,s ; set program counter back
lbra zbkpnt ; go do breakpoint
2$: clr *swibfl ; clear in case set
pulu d ; obtain function byte, up pc
cmpb #numfun ; ? too high
lbhi error ; yes, do breakpoint
stu 10,s ; bump program counter past swi
aslb ; function code times two
leau swivtb,pcr ; obtain vector branch address
ldd b,u ; load offset
jmp d,u ; jump to routine
.page
.sbttl Monitor Entry
;********************************************************
;* registers to function routines:
;* dp-> work area page
;* d,y,u=unreliable x=as called from user
;* s=as from swi interrupt
;********************************************************
;********************************************************
;* [swi function 8]
;* monitor entry
;*
;* fireup the assist09 monitor.
;* the stack with its values for the direct page
;* register and condition code flags are used as is.
;* 1) initialize console i/o
;* 2) optionally print signon
;* 3) enter command processor
;*
;* input: a=0 init console and print startup message
;* a#0 omit console init and startup message
;********************************************************
signon: .ascii /Assist09 -- 6809 Monitor/ ; signon eye-catcher
.byte eot
zmontr: sts *rstack ; save for bad stack recovery
tst 1,s ; ? init console and send msg
bne 1$ ; branch if not
jsr [vectab+.cion,pcr] ; ready console input
jsr [vectab+.coon,pcr] ; ready console output
leax signon,pcr ; ready signon eye-catcher
swi ; perform
.byte pdata ; print string
1$: ; fall through to cmd
.page
.sbttl Command Processor
;********************************************************
;* command handler
;*
;* breakpoints are removed at this time.
;* prompt for a command, and store all characters
;* until a separator on the stack.
;* search for first matching command subset,
;* call it or give '?' response.
;*
;* during command search:
;* b=offset to next entry on x
;* u=saved s
;* u-1=entry size+2
;* u-2=valid number flag (>=0 valid)/compare cnt
;* u-3=carriage return flag (0=cr has been done)
;* u-4=start of command store
;* s+0=end of command store
;********************************************************
;********************************************************
;* commands are entered as a subroutine with:
;* dpr->assist09 direct page work area
;* z=1 carriage return entered
;* z=0 non carriage return delimiter
;* s=normal return address
;*
;* the label "cmdbad" may be entered to issue an
;* an error flag (?).
;********************************************************
cmd: swi ; to new line
.byte pcrlf ; function
;* disarm the breakpoints
cmdnep: lbsr cbkldr ; obtain breakpoint pointers
bpl 2$ ; branch if not armed or none
negb ; make positive
stb *bkptct ; flag as disarmed
1$: decb ; ? finished
bmi 2$ ; branch if so
lda -numbkp*2,y ; load opcode stored
sta [,y++] ; store back over "swi"
bra 1$ ; loop until done
2$: ldx 10,s ; load users program counter
stx *pcnter ; save for expression analyzer
lda #prompt ; load prompt character
swi ; send to output handler
.byte outch ; function
leau ,s ; remember stack restore address
stu *pstack ; remember stack for error use
clra ; prepare zero
clrb ; prepare zero
std *anumber ; clear number build area
std *misflg ; clear miscel. and swicnt flags
ldb #2 ; set d to two
pshs d,cc ; place defaults onto stack
;* check for "quick" commands.
lbsr read ; obtain first character
leax cmpadp+2,pcr ; ready memory entry point
cmpa #'/ ; open last used memory ?
beq 11$ ; yes - doit
;* process next character
3$: cmpa #' ; ? blank or delimiter
bls 5$ ; branch yes, we have it
pshs a ; build onto stack
inc -1,u ; count this character
cmpa #'/ ; ? memory command
beq 12$ ; branch if so
lbsr bldhxc ; treat as hex value
beq 4$ ; branch if still valid number
dec -2,u ; flag as invalid number
4$: lbsr read ; obtain next character
bra 3$ ; test next character
;* got command, now search tables
5$: suba #cr ; set zero if carriage return
sta -3,u ; setup flag
ldx *vectab+.cmdl1 ; start with first cmd list
6$: ldb ,x+ ; load entry length
bpl 7$ ; branch if not list end
ldx *vectab+.cmdl2 ; now to second cmd list
incb ; ? to continue to default list
beq 6$ ; branch if so
cmdbad=.
lds *pstack ; restore stack
leax errmsg,pcr ; point to error string
swi ; send out
.byte pdata1 ; to console
bra cmd ; and try again
;* search next entry
7$: decb ; take account of length byte
cmpb -1,u ; ? entered longer than entry
bhs 9$ ; branch if not too long
8$: abx ; skip to next entry
bra 6$ ; and try next
9$: leay -3,u ; prepare to compare
lda -1,u ; load size+2
suba #2 ; to actual size entered
sta -2,u ; save size for countdown
10$: decb ; down one byte
lda ,x+ ; next command character
cmpa ,-y ; ? same as that entered
bne 8$ ; branch to flush if not
dec -2,u ; count down length of entry
bne 10$ ; branch if more to test
abx ; to next entry
ldd -2,x ; load offset
leax d,x ; compute routine address+2
11$: tst -3,u ; set cc for carriage return test
leas ,u ; delete stack work area
jsr -2,x ; call command
lbra 2$ ; go get next command
12$: tst -2,u ; ? valid hex number entered
bmi cmdbad ; branch error if not
leax cmemn-cmpadp,x ; to different entry
ldd *anumber ; load number entered
bra 11$ ; and enter memory command
.page
.sbttl assist09 Command Tables
;********************************************************
;* assist09 command tables
;*
;* these are the default command tables. external
;* tables of the same format may extend/replace
;* these by using the vector swap function.
;*
;* entry format:
;* +0...total size of entry (including this byte)
;* +1...command string
;* +n...two byte offset to command (entryaddr-.)
;*
;* the tables terminate with a one byte -1 or -2.
;* the -1 continues the command search with the
;* second command table.
;* the -2 terminates command searches.
;********************************************************
;* this is the default list for the second command
;* list entry.
cmdtb2: .byte -2 ; stop command searches
;* this is the default list for the first command
;* list entry.
cmdtb1: ; monitor command table
.byte 4
.ascii /B/ ; 'breakpoint' command
.word cbkpt-.
.byte 4
.ascii /C/ ; 'call' command
.word ccall-.
.byte 4
.ascii /D/ ; 'display' command
.word cdi-.
.byte 4
.ascii /E/ ; 'encode' command
.word cencde-.
.byte 4
.ascii /G/ ; 'go' command
.word cgo-.
.byte 4
.ascii /L/ ; 'load' command
.word cload-.
.byte 4
.ascii /M/ ; 'memory' command
.word cmem-.
.byte 4
.ascii /N/ ; 'nulls' command
.word cnulls-.
.byte 4
.ascii /O/ ; 'offset' command
.word coffs-.
.byte 4
.ascii /P/ ; 'punch' command
.word cpunch-.
.byte 4
.ascii /R/ ; 'registers' command
.word creg-.
.byte 4
.ascii /V/ ; 'verify' command
.word cver-.
.byte 4
.ascii /W/ ; 'window' command
.word cwindo-.
.byte -1 ; end, continue with the second
.page
.sbttl SWI Functions
;********************************************************
;* [swi functions 4 and 5]
;*
;* 4 - out2hs - decode byte to hex and add space
;* 5 - out4hs - decode word to hex and add space
;*
;* input: x->byte or word to decode
;* output: characters sent to output handler
;* x->next byte or word
;********************************************************
zout2h: lda ,x+ ; load next byte
pshs d ; save - do not reread
ldb #16 ; shift by 4 bits
mul ; with multiply
bsr zouthx ; send out as hex
puls d ; restore bytes
anda #0x0f ; isolate right hex
zouthx: adda #0x90 ; prepare a-f adjust
daa ; adjust
adca #0x40 ; prepare character bits
daa ; adjust
send: jmp [vectab+.codta,pcr] ; send to out handler
zot4hs: bsr zout2h ; convert first byte
zot2hs: bsr zout2h ; convert byte to hex
stx 4,s ; update users x register
;* fall into space routine
;********************************************************
;* [swi function 7]
;* ace - send blank to output handler
;*
;* input: none
;* output: blank send to console handler
;********************************************************
zspace: lda #' ; load blank
bra zotch2 ; send and return
;********************************************************
;* [swi function 9]
;* swap vector table entry
;*
;* input: a=vector table code (offset)
;* x=0 or replacement value
;* output: x=previous value
;********************************************************
zvswth: lda 1,s ; load requesters a
cmpa #hivtr ; ? sub-code too high
bhi zotch3 ; ignore call if so
ldy *vectab+.avtbl ; load vector table address
ldu a,y ; u=old entry
stu 4,s ; return old value to callers x
stx -2,s ; ? x=0
beq zotch3 ; yes, do not change entry
stx a,y ; replace entry
bra zotch3 ; return from swi
.page
;********************************************************
;* [swi function 0]
;* inchnp - obtain input char in a (no parity)
;*
;* nulls and rubouts are ignored.
;* automatic line feed is sent upon recieving a
;* carriage return.
;* unless we are loading from tape.
;********************************************************
zinchp: bsr xqpaus ; release processor
zinch: bsr xqcidt ; call input data appendage
bcc zinchp ; loop if none available
tsta ; test for null
beq zinch ; ignore null
cmpa #0x7f ; ? rubout
beq zinch ; branch yes to ignore
sta 1,s ; store into callers a
tst *misflg ; ? load in progress
bne zotch3 ; branch if so to not echo
cmpa #cr ; ? carriage return
bne 1$ ; no, test echo byte
lda #lf ; load line feed
bsr send ; always echo line feed
1$: tst *vectab+.echo ; ? echo desired
bne zotch3 ; no, return
;* fall through to outch
;********************************************************
;* [swi function 1]
;* outch - output character from a
;*
;* input: none
;* output: if linefeed is the output character then
;* c=0 no ctl-x recieved, c=1 ctl-x recieved
;********************************************************
zotch1: lda 1,s ; load character to send
leax zpcrls,pcr ; default for line feed
cmpa #lf ; ? line feed
beq zpdtlp ; branch to check pause if so
zotch2: bsr send ; send to output routine
zotch3: inc *swicnt ; bump up "swi" trace nest level
rti ; return from "swi" function
;********************************************************
;* [swi function 6]
;* pcrlf - send cr/lf to console handler
;*
;* input: none
;* output: cr and lf sent to handler
;* c=0 no ctl-x, c=1 ctl-x recieved
;********************************************************
zpcrls: .byte eot ; null string
zpcrlf: leax zpcrls,pcr ; ready cr,lf string
;* fall into cr/lf code
;********************************************************
;* [swi function 3]
;* pdata - output cr/lf and string
;*
;* input: x->string
;* output: cr/lf and string sent to output console
;* handler.
;* c=0 no ctl-x, c=1 ctl-x recieved
;*
;* note: line feed must follow carriage return for
;* proper punch data.
;********************************************************
zpdata: lda #cr ; load carriage return
bsr send ; send it
lda #lf ; load line feed
;* fall into pdata1
;********************************************************
;* [swi function 2]
;* pdata1 - output string till eot (0x04)
;*
;* this routine pauses if an input byte becomes
;* available during output transmission until a
;* second is recieved.
;*
;* input: x->string
;* output: string sent to output console driver
;* c=0 no ctl-x, c=1 ctl-x recieved
;********************************************************
zpdtlp: bsr send ; send character to driver
zpdta1: lda ,x+ ; load next character
cmpa #eot ; ? eot
bne zpdtlp ; loop if not
;* fall into pause check function
;********************************************************
;* [swi function 12]
;* pause - return to task dispatching and check
;*
;* for freeze condition or ctl-x break
;* this function enters the task pause handler so
;* optionally other 6809 processes may gain control.
;* upon return, check for a 'freeze' condition
;* with a resulting wait loop, or condition code
;* return if a control-x is entered from the input
;* handler.
;*
;* output: c=1 if ctl-x has entered, c=0 otherwise
;********************************************************
zpause: bsr xqpaus ; release control at every line
bsr chkabt ; check for freeze or abort
tfr cc,b ; prepare to replace cc
stb ,s ; overlay old one on stack
bra zotch3 ; return from "swi"
;* chkabt - scan for input pause/abort during output
;* output: c=0 ok, c=1 abort (ctl-x issued)
;* volatile: u,x,d
chkabt: bsr xqcidt ; attempt input
bcc 2$ ; branch no to return
cmpa #can ; ? ctl-x for abort
bne 3$ ; branch no to pause
1$: comb ; set carry
2$: rts ; return to caller with cc set
3$: bsr xqpaus ; pause for a moment
bsr xqcidt ; ? key for start
bcc 3$ ; loop until recieved
cmpa #can ; ? abort signaled from wait
beq 1$ ; branch yes
clra ; set c=0 for no abort
rts ; and return
;* save memory with jumps
xqpaus: jmp [vectab+.pause,pcr] ; to pause routine
xqcidt: jsr [vectab+.cidta,pcr] ; to input routine
anda #0x7f ; strip parity
rts ; return to caller
;* lddp - setup direct page register, verify stack.
;* an invalid stack causes a return to the command
;* handler.
;* input: fully stacked registers from an interrupt
;* output: dpr loaded to work page
errmsg: .byte '?,bell,0x20,eot ; error response
ldrtn: rts
lddp: ldb basepg,pcr ; load direct page high byte
tfr b,dp ; setup direct page register
cmpa 3,s ; ? is stack valid
beq ldrtn ; yes, return
lds *rstack ; reset to initial stack pointer
error: leax errmsg,pcr ; load error report
swi ; send out before registers
.byte pdata ; on next line
;* fall into breakpoint handler
;********************************************************
;* [swi function 10]
;* breakpoint program function
;*
;* print registers and go to command handler
;********************************************************
zbkpnt: bsr zbkstk ; stack an extra word
zbkcmd: lbra cmdnep ; now enter command handler
zbkstk: lbsr regprt ; print out registers
rts
;********************************************************
;* irq, reserved, swi2 and swi3 interrupt handlers
;* the default handling is to cause a breakpoint.
;********************************************************
swi2r: ; swi2 entry
swi3r: ; swi3 entry
irqr: ; irq entry
nmir: ; nmi entry
rsrvdr: bsr lddp ; set base page, validate stack
bra zbkpnt ; force a breakpoint
;********************************************************
;* firq handler
;* just return for the firq interrupt
;********************************************************
firqr: rti ; immediate return
.page
.sbttl Read / Verify / Punch Routines
;* bson - turn on read/verify/punch mechanism
bson: inc *misflg ; set load in progress flag
rts ; return to caller
;* bsoff - turn off read/verify/punch mechanism
;* a,x volatile
bsoff: dec *misflg ; clear load in progress flag
rts ; return to caller
;* bsdta - read/verify/punch handler
;* input: s+6=code byte, verify(-1),punch(0),load(1)
;* s+4=start address
;* s+2=stop address
;* s+0=return address
;* output: z=1 normal completion, z=0 invalid load/ver
;* registers are volatile
bsdta: ldu 2,s ; u=to address or offset
tst 6,s ; ? punch
beq 10$ ; branch yes
;* during read/verify: s+2=msb address save byte
;* s+1=byte counter
;* s+0=checksum
;* u holds offset
leas -3,s ; room for work/counter/checksum
1$: swi ; get next character
.byte inchnp ; function
2$: cmpa #'S ; ? start of s1/s9
bne 1$ ; branch not
swi ; get next character
.byte inchnp ; function
cmpa #'9 ; ? have s9
beq 5$ ; yes, return good code
cmpa #'1 ; ? have new record
bne 2$ ; branch if not
clr ,s ; clear checksum
bsr 9$ ; obtain byte count
stb 1,s ; save for decrement
;* read address
bsr 9$ ; obtain high value
stb 2,s ; save it
bsr 9$ ; obtain low value
lda 2,s ; make d=value
leay d,u ; y=address+offset
;* store text
3$: bsr 9$ ; next byte
beq 6$ ; branch if checksum
tst 9,s ; ? verify only
bmi 4$ ; yes, only compare
stb ,y ; store into memory
4$: cmpb ,y+ ; ? valid ram
beq 3$ ; yes, continue reading
5$: puls pc,x,a ; return with z set proper
6$: inca ; ? valid checksum
beq 1$ ; branch yes
bra 5$ ; return z=0 invalid
;* byte builds 8 bit value from two hex digits in
7$: bsr 9$ ; obtain first hex
ldb #16 ; prepare shift
mul ; over to a
bsr 9$ ; obtain second hex
pshs b ; save high hex
adda ,s+ ; combine both sides
tfr a,b ; send back in b
adda 2,s ; compute new checksum
sta 2,s ; store back
dec 3,s ; decrement byte count
8$: rts ; return to caller
9$: swi ; get next hex
.byte inchnp ; character
lbsr cnvhex ; convert to hex
beq 8$ ; return if valid hex
puls pc,u,y,x,a ; return to caller with z=0
;* punch stack use: s+8=to address
;* s+6=return address
;* s+4=saved padding values
;* s+2 from address
;* s+1=frame count/checksum
;* s+0=byte count
10$: ldu *vectab+.pad ; load padding values
ldx 4,s ; x=from address
pshs u,x,d ; create stack work area
ldd #24 ; set a=0, b=24
stb *vectab+.pad ; setup 24 character pads
swi ; send nulls out
.byte outch ; function
ldb #4 ; setup new line pad to 4
std *vectab+.pad ; setup punch padding
;* calculate size
11$: ldd 8,s ; load to
subd 2,s ; minus from=length
cmpd #24 ; ? more than 23
blo 12$ ; no, ok
ldb #23 ; force to 23 max
12$: incb ; prepare counter
stb ,s ; store byte count
addb #3 ; adjust to frame count
stb 1,s ; save
;*punch cr,lf,nuls,s,1
leax 16$,pcr ; load start record header
swi ; send out
.byte pdata ; function
;* send frame count
clrb ; initialize checksum
leax 1,s ; point to frame count and addr
bsr 14$ ; send frame count
;*data address
bsr 14$ ; send address hi
bsr 14$ ; send address low
;*punch data
ldx 2,s ; load start data address
13$: bsr 14$ ; send out next byte
dec ,s ; ? final byte
bne 13$ ; loop if not done
stx 2,s ; update from address value
;*punch checksum
comb ; complement
stb 1,s ; store for sendout
leax 1,s ; point to it
bsr 15$ ; send out as hex
ldx 8,s ; load top address
cmpx 2,s ; ? done
bhs 11$ ; branch not
leax 17$,pcr ; prepare end of file
swi ; send out string
.byte pdata ; function
ldd 4,s ; recover pad counts
std *vectab+.pad ; restore
clra ; set z=1 for ok return
puls pc,u,x,d ; return with ok code
14$: addb ,x ; add to checksum
15$: lbra zout2h ; send out as hex and return
16$: .byte 'S,'1,eot ; cr,lf,nulls,S,1
17$: .ascii /S9030000FC/ ; eof string
.byte cr,lf,eot
;* hsdta - high speed print memory
;* input: s+4=start address
;* s+2=stop address
;* s+0=return address
;* x,d volatile
;* send title
hsdta: swi ; send new line
.byte pcrlf ; function
ldb #6 ; prepare 6 spaces
1$: swi ; send blank
.byte space ; function
decb ; count down
bne 1$ ; loop if more
clrb ; setup byte count
2$: tfr b,a ; prepare for convert
lbsr zouthx ; convert to a hex digit
swi ; send blank
.byte space ; function
swi ; send another
.byte space ; blank
incb ; up another
cmpb #0x10 ; ? past 'f'
blo 2$ ; loop until so
3$: swi ; to next line
.byte pcrlf ; function
bcs 8$ ; return if user entered ctl-x
leax 4,s ; point at address to convert
swi ; print out address
.byte out4hs ; function
ldx 4,s ; load address proper
ldb #16 ; next sixteen
4$: swi ; convert byte to hex and send
.byte out2hs ; function
decb ; count down
bne 4$ ; loop if not sixteenth
swi ; send blank
.byte space ; function
ldx 4,s ; reload from address
ldb #16 ; count
5$: lda ,x+ ; next byte
bmi 6$ ; too large, to a dot
cmpa #' ; ? lower than a blank
bhs 7$ ; no, branch ok
6$: lda #'. ; convert invalid to a blank
7$: swi ; send character
.byte outch ; function
decb ; ? done
bne 5$ ; branch no
cpx 2,s ; ? past last address
bhs 8$ ; quit if so
stx 4,s ; update from address
lda 5,s ; load low byte address
asla ; ? to section boundry
bne 3$ ; branch if not
bra hsdta ; branch if so
8$: swi ; send new line
.byte pcrlf ; function
rts ; return to caller
;********************************************************
;* a s s i s t 0 9 c o m m a n d s
;********************************************************
;********** registers - display and change registers
creg: bsr regprt ; print registers
inca ; set for change function
bsr regchg ; go change, display registers
rts ; return to command processor
;********************************************************
;* regprt - print/change registers subroutine
;* will abort to 'cmdbad' if overflow detected during
;* a change operation. change displays registers when
;* done.
;*
;* register mask list consists of:
;* a) characters denoting register
;* b) zero for one byte, -1 for two
;* c) offset on stack to register position
;*
;* input: +4=stacked registers
;* a=0 print, a#0 print and change
;* output: (only for register display)
;* c=1 control-x entered, c=0 otherwise
;*
;* volatile: d,x (change)
;* b,x (display)
;********************************************************
regmsk: .byte 'P,'C,-1,19 ; pc reg
.byte 'A,0,10 ; a reg
.byte 'B,0,11 ; b reg
.byte 'X,-1,13 ; x reg
.byte 'Y,-1,15 ; y reg
.byte 'U,-1,17 ; u reg
.byte 'S,-1,1 ; s reg
.byte 'C,'c,0,9 ; cc reg
.byte 'D,'p,0,12 ; dp reg
.byte 0 ; end of list
regprt: clra ; setup print only flag
regchg: leax 4+12,s ; ready stack value
pshs y,x,a ; save on stack with option
leay regmsk,pcr ; load register mask
1$: ldd ,y+ ; load next char or <=0
tsta ; ? end of characters
ble 2$ ; branch not character
swi ; send to console
.byte outch ; function byte
bra 1$ ; check next
2$: lda #'- ; ready '-'
swi ; send out
.byte outch ; with outch
leax b,s ; x->register to print
tst ,s ; ? change option
bne 5$ ; branch yes
tst -1,y ; ? one or two bytes
beq 3$ ; branch zero means one
swi ; perform word hex
.byte out4hs ; function
bra 4$
3$: swi ; perform byte hex
.byte out2hs ; function
4$: ldd ,y+ ; to front of next entry
tstb ; ? end of entries
bne 1$ ; loop if more
swi ; force new line
.byte pcrlf ; function
puls pc,y,x,a ; restore stack and return
5$: bsr bldnnb ; input binary number
beq 7$ ; if change then jump
cmpa #cr ; ? no more desired
beq 9$ ; branch nope
ldb -1,y ; load size flag
decb ; minus one
negb ; make positive
aslb ; times two (=2 or =4)
6$: swi ; perform spaces
.byte space ; function
decb
bne 6$ ; loop if more
bra 4$ ; continue with next register
7$: sta ,s ; save delimiter in option
;* (always > 0)
ldd *anumber ; obtain binary result
tst -1,y ; ? two bytes worth
bne 8$ ; branch yes
lda ,-x ; setup for two
8$: std ,x ; store in new value
lda ,s ; recover delimiter
cmpa #cr ; ? end of changes
bne 4$ ; no, keep on truck'n
;* move stacked data to new stack in case stack
;* pointer has changed
9$: leax tstack,pcr ; load temp area
ldb #21 ; load count
10$: puls a ; next byte
sta ,x+ ; store into temp
decb ; count down
bne 10$ ; loop if more
lds -20,x ; load new stack pointer
ldb #21 ; load count again
11$: lda ,-x ; next to store
pshs a ; back onto new stack
decb ; count down
bne 11$ ; loop if more
puls pc,y,x,a ; restore stack and return
;********************************************************
;* bldnum - builds binary value from input hex
;* the active expression handler is used.
;*
;* input: s=return address
;* output: a=delimiter which terminated value
;* (if delm not zero)
;* "number"=word binary result
;* z=1 if input recieved, z=0 if no hex recieved
;*
;* registers are transparent
;********************************************************
;* execute single or extended rom expression handler
;*
;* the flag "delim" is used as follows:
;* delim=0 no leading blanks, no forced terminator
;* delim=chr accept leading 'chr's, forced terminator
bldnnb: clra ; no dynamic delimiter
sta *delim ; store as delimiter
jmp [vectab+.expan,pcr] ; to exp analyzer
;* build with leading blanks
bldnum: lda #' ; allow leading blanks
sta *delim ; store as delimiter
jmp [vectab+.expan,pcr] ; to exp analyzer
;* this is the default single rom analyzer. we accept:
;* 1) hex input
;* 2) 'M' for last memory examine address
;* 3) 'P' for program counter address
;* 4) 'W' for window value
;* 5) '@' for indirect value
exp1: pshs x,b ; save registers
1$: bsr bldhxi ; clear number, check first char
beq 3$ ; if hex digit continue building
;* skip blanks if desired
cmpa *delim ; ? correct delimiter
beq 1$ ; yes, ignore it
;* test for m or p
ldx *addr ; default for 'm'
cmpa #'M ; ? memory examine addr wanted
beq 5$ ; branch if so
ldx *pcnter ; default for 'p'
cmpa #'P ; ? last program counter wanted
beq 5$ ; branch if so
ldx *window ; default to window
cmpa #'W ; ? window wanted
beq 5$
2$: puls pc,x,b ; return and restore registers
;* got hex, now continue building
3$: bsr bldhex ; compute next digit
beq 3$ ; continue if more
bra 6$ ; search for +/-
;* store value and check if need delimiter
4$: ldx ,x ; indirection desired
5$: stx *anumber ; store result
tst *delim ; ? to force a delimiter
beq 2$ ; return if not with value
bsr read ; obtain next character
;* test for + or -
6$: ldx *anumber ; load last value
cmpa #'+ ; ? add operator
bne 8$ ; branch not
bsr 10$ ; compute next term
pshs a ; save delimiter
ldd *anumber ; load new term
7$: leax d,x ; add to x
stx *anumber ; store as new result
puls a ; restore delimiter
bra 6$ ; now test it
8$: cmpa #'- ; ? subtract operator
beq 9$ ; branch if so
cmpa #'@ ; ? indirection desired
beq 4$ ; branch if so
clrb ; set delimiter return
bra 2$ ; and return to caller
9$: bsr 10$ ; obtain next term
pshs a ; save delimiter
ldd *anumber ; load up next term
nega ; negate a
negb ; negate b
sbca #0 ; correct for a
bra 7$ ; go add to expresion
;* compute next expression term
;* output: x=old value
;* 'number'=next term
10$: bsr bldnum ; obtain next value
lbne cmdbad ; abort command if invalid
rts ; return if valid number
;********************************************************
;* build binary value using input characters.
;*
;* input: a=ascii hex value or delimiter
;* +0=return address
;* +2=16 bit result area
;* output: z=1 a=binary value
;* z=0 if invalid hex character (a unchanged)
;*
;* volatile: d
;********************************************************
bldhxi: clr *anumber ; clear number
clr *anumber+1 ; clear number
bldhex: bsr read ; get input character
bldhxc: bsr cnvhex ; convert and test character
bne cnvrts ; return if not a number
ldb #16 ; prepare shift
mul ; by four places
lda #4 ; rotate binary into value
1$: aslb ; obtain next bit
rol *anumber+1 ; into low byte
rol *anumber ; into hi byte
deca ; count down
bne 1$ ; branch if more to do
bra cnvok ; set good return code
;********************************************************
;* convert ascii character to binary byte
;*
;* input: a=ascii
;* output: z=1 a=binary value
;* z=0 if invalid
;*
;* all registers transparent
;* (a unaltered if invalid hex)
;********************************************************
cnvhex: cmpa #'0 ; ? lower tigh hex
blo cnvrts ; branch not value
cmpa #'9 ; ? possible a-f
ble cnvgot ; branch no to accept
cmpa #'A ; ? less than ten
blo cnvrts ; return if minus (invalid)
cmpa #'F ; ? not too large
bhi cnvrts ; no, return too large
suba #7 ; down to binary
cnvgot: anda #0x0f ; clear high byte
cnvok: orcc #4 ; force zero on for valid hex
cnvrts: rts ; return to caller
;* get input char, abort command if control-x (cancel)
read: swi ; get next character
.byte inchnp ; function
cmpa #can ; ? abort command
lbeq cmdbad ; branch to abort if so
rts ; return to caller
;************ console - dumby routines
cidta: clc ; never a character
codta: ; dumby character out
cion: ; input console initialization
coon: ; output console initialization
cioff: ; console input off
cooff: ; console output off
cirtn: rts
;************ pause - process pause routine
cpause: jmp pauser ; go to default pause routine
;************ go - start program execution
cgo: bsr goaddr ; build address if needed
rti ; start executing
;* find optional new program counter. also arm the
;* breakpoints.
goaddr: puls y,x ; pop return addresses from cmd and cgo
pshs x ; restore return from cgo
beq 1$ ; <cr> ? yes - use current pc
;* obtain new program counter
lbsr cdnum ; obtain new program counter
std 12,s ; store into stack
1$: ldx 12,s ; load program counter
lbsr cbkldr ; obtain table
neg *bkptct ; complement to show armed
2$: decb ; ? done
bmi 5$ ; return when done
lda [,y] ; load opcode
sta -numbkp*2,y ; store into opcode table
lda #0x3f ; ready "swi" opcode
cmpx ,y ; starting at a breakpoint ?
bne 4$ ; no - go set breakpoint
cmpa [,y++] ; ? swi breakpointed
bne 2$ ; no, skip setting of flag
sta *swibfl ; show upcomming swi not brkpnt
bra 2$ ; check others
4$: sta [,y++] ; store and move up table
bra 2$ ; and continue
5$: rts
;************ call - call address as subroutine
ccall: bsr goaddr ; fetch address if needed
puls u,y,x,dp,d,cc ; restore users registers
jsr [,s++] ; call user subroutine
1$: swi ; perform breakpoint
.byte brkpt ; function
bra 1$ ; loop until user changes pc
;************ memory - display/change memory
;* cmem and cmpadp are direct entry points from
;* the command handler for quick commands
cmem: lbsr cdnum ; obtain address
cmemn: std *addr ; store default
1$: ldx *addr ; load pointer
lbsr zout2h ; send out hex value of byte
lda #'- ; load delimiter
swi ; send out
.byte outch ; function
2$: lbsr bldnnb ; obtain new byte value
beq 3$ ; branch if number
;* coma - skip byte
cmpa #', ; ? comma
bne 4$ ; branch not
stx *addr ; update pointer
leax 1,x ; to next byte
bra 2$ ; and input it
3$: ldb *anumber+1 ; load low byte value
bsr 13$ ; go overlay memory byte
cmpa #', ; ? continue with no display
beq 2$ ; branch yes
;* quoted string
4$: cmpa #'' ; ? quoted string
bne 6$ ; branch no
5$: bsr read ; obtain next character
cmpa #'' ; ? end of quoted string
beq 7$ ; yes, quit string mode
tfr a,b ; to b for subroutine
bsr 13$ ; go update byte
bra 5$ ; get next character
;* blank - next byte
6$: cmpa #0x20 ; ? blank for next byte
bne 8$ ; branch not
stx *addr ; update pointer
7$: swi ; give space
.byte space ; function
bra 1$
;* dot - next byte with address
8$: cmpa #'. ; ? dot for next byte
bne 9$ ; branch no
swi ; force new line
.byte pcrlf ; function
stx *addr ; store next address
bra cmpadp ; branch to show
;* up arrow - previous byte and address
9$: cmpa #'^ ; ? up arrow for previous byte
bne 11$ ; branch not
leax -2,x ; down to previous byte
stx *addr ; store new pointer
10$: swi ; force new line
.byte pcrlf ; function
cmpadp=.
bsr 12$ ; go print its value
bra 1$ ; then prompt for input
;* slash - for current byte with address
11$: cmpa #'/ ; ? slash for current display
beq 10$ ; yes, send address
rts ; return from command
;* print current address
12$: ldx *addr ; load pointer value
pshs x ; save x on stack
leax ,s ; point to it for display
swi ; display pointer in hex
.byte out4hs ; function
puls pc,x ; recover pointer and return
;* update byte
13$: ldx *addr ; load next byte pointer
stb ,x+ ; store and increment x
cmpb -1,x ; ? successfull store
bne 14$ ; branch for '?' if not
stx *addr ; store new pointer value
rts ; back to caller
14$: pshs a ; save a register
lda #'? ; show invalid
swi ; send out
.byte outch ; function
puls pc,a ; return to caller
;************ window - set window value
cwindo: bsr cdnum ; obtain window value
std *window ; store it in
rts ; end command
;************ display - high speed display memory
cdi: bsr cdnum ; fetch address
andb #0xf0 ; force to 16 boundry
tfr d,y ; save in y
leax 15,y ; default length
bcs 1$ ; branch if end of input
bsr cdnum ; obtain count
leax d,y ; assume count, compute end addr
1$: pshs y,x ; setup parameters for hsdata
cmpd 2,s ; ? was it count
bls 2$ ; branch yes
std ,s ; store high address
2$: jsr [vectab+.hsdta,pcr] ; call print routine
puls pc,u,y ; clean stack and end command
;* obtain number - abort if none
;* only delimiters of cr, blank, or '/' are accepted
;* output: d=value, c=1 if carriage return delmiter,
;* else c=0
cdnum: lbsr bldnum ; obtain number
lbne cmdbad ; branch if invalid
cmpa #'/ ; ? valid delimiter
lbhi cmdbad ; branch if not for error
cmpa #cr+1 ; leave compare for carriage ret
ldd *anumber ; load number
rts
;************ punch - punch memory in s1-s9 format
cpunch: bsr cdnum ; obtain start address
tfr d,y ; save in y
bsr cdnum ; obtain end address
clr ,-s ; setup punch function code
pshs y,d ; store values on stack
ccalbs: jsr [vectab+.bson,pcr] ; initialize handler
jsr [vectab+.bsdta,pcr] ; perform function
pshs cc ; save return code
jsr [vectab+.bsoff,pcr] ; turn off handler
puls cc ; obtain condition code saved
lbne cmdbad ; branch if error
puls pc,y,x,a ; return from command
;************ load - load memory from s1-s9 format
cload: bsr clvofs ; call setup and pass code
.byte 1 ; load function code for packet
clvofs: leau [,s++] ; load code in high byte of u
leau [,u] ; not changing cc and restore s
beq 1$ ; branch if carriage return next
bsr cdnum ; obtain offset
bra 2$
1$: clra ; create zero offset
clrb ; as default
2$: pshs u,dp,d ; setup code, null word, offset
bra ccalbs ; enter call to bs routines
;************ verify - compare memory with files
cver: bsr clvofs ; compute offset if any
.byte -1 ; verify fnctn code for packet
;************ nulls - set new line and char padding
cnulls: bsr cdnum ; obtain new line pad
std *vectab+.pad ; reset values
rts ; end command
;************ offset - compute short and long
;* branch offsets
coffs: bsr cdnum ; obtain instruction address
tfr d,x ; use as from address
bsr cdnum ; obtain to address
;* d=to instruction, x=from instruction offset byte(s)
leax 1,x ; adjust for *+2 short branch
pshs y,x ; store work word and value on s
subd ,s ; find offset
std ,s ; save over stack
leax 1,s ; point for one byte display
sex ; sign extend low byte
cmpa ,s ; ? valid one byte offset
bne 1$ ; branch if not
swi ; show one byte offset
.byte out2hs ; function
1$: ldu ,s ; reload offset
leau -1,u ; convert to long branch offset
stu ,x ; store back where x points now
swi ; show two byte offset
.byte out4hs ; function
swi ; force new line
.byte pcrlf ; function
puls pc,x,d ; restore stack and end command
;************ breakpoint - display/enter/delete/clear
;* breakpoints
cbkpt: beq 5$ ; branch display of just 'b'
lbsr bldnum ; attempt value entry
beq 7$ ; branch to add if so
cmpa #'- ; ? correct delimiter
bne 9$ ; no, branch for error
lbsr bldnum ; attempt delete value
beq 2$ ; got one, go delete it
clr *bkptct ; was 'b -', so zero count
1$: rts ; end command
;* delete the entry
2$: bsr 11$ ; setup registers and value
3$: decb ; ? any entries in table
bmi 9$ ; branch no, error
cmpx ,y++ ; ? is this the entry
bne 3$ ; no, try next
;* found, now move others up in its place
4$: ldx ,y++ ; load next one up
stx -4,y ; move down by one
decb ; ? done
bpl 4$ ; no, continue move
dec *bkptct ; decrement breakpoint count
5$: bsr 11$ ; setup registers and load value
beq 1$ ; return if none to delete
6$: leax ,y++ ; point to next entry
swi ; display in hex
.byte out4hs ; function
decb ; count down
bne 6$ ; loop if more to do
swi ; skip to new line
.byte pcrlf ; function
rts ; return to end command
;* add new entry
7$: bsr 11$ ; setup registers
cmpb #numbkp ; ? already full
beq 9$ ; branch error if so
lda ,x ; load byte to trap
stb ,x ; try to change
cmpb ,x ; ? changable ram
bne 9$ ; branch error if not
sta ,x ; restore byte
8$: decb ; count down
bmi 10$ ; branch if done to add it
cmpx ,y++ ; ? entry already here
bne 8$ ; loop if not
9$: lbra cmdbad ; exit with error
10$: stx ,y ; add this entry
clr -numbkp*2+1,y ; clear optional byte
inc *bkptct ; add one to count
bra 5$ ; and now display all of 'em
;* setup registers for scan
11$: ldx *anumber ; load value desired
cbkldr: leay bkptbl,pcr ; load start of table
ldb *bkptct ; load entry count
rts ; return
;************ encode - encode a postbyte
cencde: clr ,-s ; default to not indirect
clrb ; zero postbyte value
leax conv1,pcr ; start table search
swi ; obtain first character
.byte inchnp ; function
cmpa #'[ ; ? indirect here
bne 2$ ; branch if not
lda #0x10 ; set indirect bit on
sta ,s ; save for later
1$: swi ; obtain next character
.byte inchnp ; function
2$: cmpa #cr ; ? end of entry
beq 4$ ; branch yes
3$: tst ,x ; ? end of table
lbmi cmdbad ; exit with error
cmpa ,x++ ; ? this the character
bne 3$ ; branch if not
addb -1,x ; add this value
bra 1$ ; get next input
4$: leax conv2,pcr ; point at table 2
tfr b,a ; save copy in a
anda #0x60 ; isolate register mask
ora ,s ; add in indirection bit
sta ,s ; save back as postbyte skeleton
andb #0x9f ; clear register bits
5$: tst ,x ; ? end of table
lbeq cmdbad ; exit with error
cmpb ,x++ ; ? same value
bne 5$ ; loop if not
ldb -1,x ; load result value
orb ,s ; add to base skeleton
stb ,s ; save postbyte on stack
leax ,s ; point to it
swi ; send out as hex
.byte out2hs ; function
swi ; to next line
.byte pcrlf ; function
puls pc,b ; end of command
;* table one defines valid input in sequence
conv1: .byte 'A,0x04,'B,0x05,'D,0x06,'H,0x01
.byte 'H,0x01,'H,0x01,'H,0x00,',,0x00
.byte '-,0x09,'-,0x01,'S,0x70,'Y,0x30
.byte 'U,0x50,'X,0x10,'+,0x07,'+,0x01
.byte 'P,0x80,'C,0x00,'R,0x00,'],0x00
.byte 0xff ; end of table
;*conv2 uses above conversion to set postbyte
;* bit skeleton.
conv2: .word 0x1084,0x1100 ; R, H,R
.word 0x1288,0x1389 ; HH,R HHHH,R
.word 0x1486,0x1585 ; A,R B,R
.word 0x168b,0x1780 ; D,R ,R+
.word 0x1881,0x1982 ; ,R++ ,-R
.word 0x1a83,0x828c ; ,--R HH,pcr
.word 0x838d,0x039f ; HHHH,pcr [HHHH]
.byte 0 ; end of table
;****************************************************
;* default interrupt transfers *
;****************************************************
rsrvd: jmp [vectab+.rsvd,pcr] ; reserved vector
swi3: jmp [vectab+.swi3,pcr] ; swi3 vector
swi2: jmp [vectab+.swi2,pcr] ; swi2 vector
firq: jmp [vectab+.firq,pcr] ; firq vector
irq: jmp [vectab+.irq,pcr] ; irq vector
swi: jmp [vectab+.swi,pcr] ; swi vector
nmi: jmp [vectab+.nmi,pcr] ; nmi vector
.page
.sbttl Hardware Interrupt Tables
;********************************************************
;* assist09 hardware vector table
;*
;* this table is used if the assist09 rom addresses
;* the mc6809 hardware vectors.
;********************************************************
.= bldvtr+0d2048-0d16 ; assume 2K ROM
.word rsrvd ; reserved slot
.word swi3 ; software interrupt 3
.word swi2 ; software interrupt 2
.word firq ; fast interrupt request
.word irq ; interrupt request
.word swi ; software interrupt
.word nmi ; non-maskable interrupt
.word reset ; restart